/* sleep.c : sleep device (assignment 2)
 */

#include <xeroskernel.h>

int convert_to_ticks(unsigned int milliseconds);
void printsleepQ( void );

static pcb *sleep_list = NULL;

int convert_to_ticks(unsigned int milliseconds) {
	return (milliseconds/MS_PER_SLICE)+1;		//+1 to round tick up.
}

/***************************************
*Sleep
*Turns requested sleep time into system ticks(indicated by timer)
*Inserts itself into a delta structed sleep list.
***************************************/
void sleep(pcb *p, unsigned int milliseconds) {
	pcb *currpos = sleep_list;
	pcb *prevpos = NULL;
	Bool setflag = 0;
	//convert ms to ticks
	p->sleepticks = convert_to_ticks(milliseconds);
	p->next = NULL;
	
	while(!setflag) {
		if(currpos == NULL) {		//current is null means Q empty or we're at the end of Q list
			//insert infront only
			if(prevpos == NULL) 	//empty sleep_list
				sleep_list = p;		
			else {									//at the last node
				prevpos->next = p;	
			} 
			setflag = TRUE;
		} else {	//current exists
			// insert if behind curr only
			if(currpos->sleepticks < p->sleepticks) {		// more ticks than current
				p->sleepticks = p->sleepticks - currpos->sleepticks;		//delta of current node
				prevpos = currpos;
				currpos = currpos->next;	
			} else { 										// insert between curr and prev
				currpos->sleepticks = currpos->sleepticks - p->sleepticks;
				p->next = currpos;
				if(prevpos != NULL) prevpos->next = p;
				else sleep_list = p;
				setflag = TRUE;
			}

		}
	}

	return;
}

/**********************************************
*Tick
*Checks for processes to wake up
**********************************************/
void tick(void) {
	pcb *p;
	if(sleep_list == NULL) return;
	//decrement head tick counter
	sleep_list->sleepticks -= 1;
	
	//wake up all processes in Q that are at sleeptick 0
	while(sleep_list->sleepticks <= 0) {
		p = sleep_list;
		//wake up and set in readyQ
		sleep_list = sleep_list->next;		
		ready(p);
	}
	return;
}

void printsleepQ() {
	pcb *p = sleep_list;
	if(p->next == NULL) {
		kprintf("Top: %d->%d \n",p->pid,p->sleepticks);
	} else {
		while(p->next != NULL) {
			kprintf("top: %d->%d, ",p->pid,p->sleepticks);
			p = p->next;
		}
		kprintf(" %d->%d \n",p->pid, p->sleepticks);
		
	}
}

// /*******************************************
// Wake up the pcb in sleep list.
// *******************************************/
// void wakeup( pcb *p ) {
// 	//find p in sleep list
// 	pcb *sl;
// 	int currticks;
// 	if( sl == p && p->next == NULL ) {

// 	} else if( sl->next == )
// 	sl = sleep_list;
// 	while(sl->next != NULL || p != sl->next) {
// 		sl = sl->next;
// 	}
// 	if(sl == NULL ) return; //kinda just wanna assume it's in the list

// 	if( sl->next->next == NULL ) {
// 		p->state = STATE_READY;
// 	}
// 	// rearrange q
// 	currticks = sl->sleepticks;
// 	sl = sl->next
// }